package com.videoaggre.zcl.ui.fragment

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.lifecycleScope
import com.videoaggre.zcl.api.ApiObserver
import com.videoaggre.zcl.api.ApiRequest
import com.videoaggre.zcl.helper.OnStartActivityListener
import com.videoaggre.zcl.ui.activity.ActivityForResult
import com.videoaggre.zcl.ui.activity.RequestMultiplePermissions
import com.videoaggre.zcl.utils.Logger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import java.io.Serializable

/**
 * Created by zhoucl on 2016/11/7.
 */
fun <T> Fragment.launchUI(
    block: suspend CoroutineScope.() -> T,
    apiObserver: ApiObserver<T>? = null,
    error: ((Throwable) -> Unit)? = null,
    complete: (() -> Unit)? = null
): Job = ApiRequest(lifecycleScope).launchUI(block, error, complete, apiObserver)
inline fun <reified T : Fragment> Fragment.put(pair: Pair<String, Any>): T {
    if (arguments == null) {
        arguments = Bundle()
    }
    arguments?.run {
        val name = pair.first
        when (val value = pair.second) {
            is Int -> putInt(name, value)
            is Byte -> putByte(name, value)
            is Char -> putChar(name, value)
            is Short -> putShort(name, value)
            is Boolean -> putBoolean(name, value)
            is Long -> putLong(name, value)
            is Float -> putFloat(name, value)
            is Double -> putDouble(name, value)
            is String -> putString(name, value)
            is CharSequence -> putCharSequence(name, value)
            is Parcelable -> putParcelable(name, value)
            is Array<*> -> putSerializable(name, value)
            is ArrayList<*> -> putSerializable(name, value)
            is Serializable -> putSerializable(name, value)
            is BooleanArray -> putBooleanArray(name, value)
            is ByteArray -> putByteArray(name, value)
            is ShortArray -> putShortArray(name, value)
            is CharArray -> putCharArray(name, value)
            is IntArray -> putIntArray(name, value)
            is LongArray -> putLongArray(name, value)
            is FloatArray -> putFloatArray(name, value)
            is DoubleArray -> putDoubleArray(name, value)
            is Bundle -> putBundle(name, value)
            else -> {
            }
        }
    }
    return this as T
}

abstract class BaseFragment(private var layoutResID: Int? = null) : Fragment(), View.OnClickListener, OnStartActivityListener {
    protected var mView: View? = null
    protected var mSavedInstanceState: Bundle? = null
    private val dispatcher by lazy { requireActivity().onBackPressedDispatcher }
    private val callback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            onBackPressed()
        }
    }
    private var mActivityForResult: ActivityForResult? = null
    private var mIsNeedResultOk: Boolean? = null
    private var mRequestMultiplePermissions: RequestMultiplePermissions? = null
    private val mStartActivityForResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult ->
        if (mIsNeedResultOk == true) {
            if (activityResult.resultCode == AppCompatActivity.RESULT_OK)
                mActivityForResult?.invoke(activityResult)
        } else {
            mActivityForResult?.invoke(activityResult)
        }
    }
    private val mRequestMultiplePermissionsLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { activityResult ->
        mRequestMultiplePermissions?.invoke(activityResult)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        dispatcher.addCallback(this, callback)
    }

    fun onBackPressed() {
        callback.isEnabled = false
        dispatcher.onBackPressed()
    }

    fun hasExtras(): Boolean {
        return arguments != null
    }

    override fun getView(): View? {
        return mView
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        try {
            mView = if (layoutResID != null) {
                inflater.inflate(layoutResID!!, null)
            } else {
                super.onCreateView(inflater, container, savedInstanceState)
            }
            mSavedInstanceState = savedInstanceState
            init(mView, savedInstanceState)
            initView(mView, savedInstanceState)
            initData(mView, savedInstanceState)
        } catch (e: Exception) {
            Logger.e(e)
        }
        return mView
    }

    override fun onClick(v: View?) {

    }

    open fun init(rootView: View?, savedInstanceState: Bundle?) {}
    open fun initView(rootView: View?, savedInstanceState: Bundle?) {}
    open fun initData(rootView: View?, savedInstanceState: Bundle?) {}

    fun onWindowFocusChanged(hasFocus: Boolean) {}
    fun bindViewClick(vararg views: View) = com.videoaggre.zcl.common.bindViewClick(this, *views)
    open fun launchStartActivityForResult(clazz: Class<*>, options: Bundle? = null, isNeedResultOk: Boolean = false, activityForResult: ActivityForResult? = null) {
        val intent = Intent(context, clazz)
        options?.let { intent.putExtras(it) }
        mActivityForResult = activityForResult
        mIsNeedResultOk = isNeedResultOk
        mStartActivityForResultLauncher.launch(intent)
    }

    open fun launchRequestMultiplePermissions(permissions: Array<String>, requestMultiplePermissions: RequestMultiplePermissions? = null) {
        mRequestMultiplePermissions = requestMultiplePermissions
        mRequestMultiplePermissionsLauncher.launch(permissions)
    }

    override fun goActicity(clazz: Class<*>, bundle: Bundle?, requestCode: Int?) {
        val intent = Intent(context, clazz)
        bundle?.let { intent.putExtras(it) }
        if (requestCode != null) {
            startActivityForResult(intent, requestCode)
        } else {
            startActivity(intent)
        }
    }

    override fun goActicityFinish(clazz: Class<*>, bundle: Bundle?, requestCode: Int?) {
        goActicity(clazz, bundle, requestCode)
        activity?.finish()
    }

}